//
//  LoginQRViewController.swift
//  kz
//
//  Created by Tech_001 on 1/8/2017.
//  Copyright © 2017 Tech_001. All rights reserved.
//

import Foundation
import UIKit
import AVFoundation

protocol LoginQRViewControllerDelegate
{
    func merchantResponse(_ url: URL, _ dataArray: [String:String])
}

extension URL {
    var queryItemsDictionary: [String: String] {
        var queryItemsDictionary = [String: String]()
        guard let components = URLComponents(url: self, resolvingAgainstBaseURL: false), let queryItems = components.queryItems else { return queryItemsDictionary }
        queryItems.forEach { queryItemsDictionary[$0.name] = $0.value }
        return queryItemsDictionary
    }
}


@available(iOS 9.0, *)
class LoginQRViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate{
    var captureSession:AVCaptureSession?
    var videoPreviewLayer:AVCaptureVideoPreviewLayer?
    var captureMetadataOutput: AVCaptureMetadataOutput?
    var qrCodeFrameView:UIView?
    var qrValue:String?
    
    var delegate: LoginQRViewControllerDelegate?
    var imagePicker = UIImagePickerController()
    
    var _loadView: UIView?
    
    @IBOutlet weak var topMarginView: UIView!
    @IBOutlet weak var qrInterestView: UIView!
    //@IBOutlet weak var bottomStackView: UIStackView!
    
    @IBOutlet weak var loadingOverlayiew: UIView!
    @IBOutlet weak var loadingIndicatorContainerView: UIView!
    @IBOutlet weak var loadingIndicatorView: UIActivityIndicatorView!
    
    /**** Controller Events ****/
    override func viewDidLoad() {
        super.viewDidLoad()
        
        loadingIndicatorContainerView.layer.cornerRadius = 5
        loadingOverlayiew.layer.isHidden = true
        // 取得 AVCaptureDevice 類別的實體來初始化一個device物件，並提供video
        // 作為媒體型態參數
        
        let captureDevice = AVCaptureDevice.default(for: AVMediaType.video)
        
        // 使用前面的 device 物件取得 AVCaptureDeviceInput 類別的實體
        do{
            let input: AnyObject! = try AVCaptureDeviceInput(device: captureDevice!)
            // 初始化 captureSession 物件
            captureSession = AVCaptureSession()
            // 在capture session 設定輸入裝置
            captureSession?.addInput(input as! AVCaptureInput)
            
            // 初始化 AVCaptureMetadataOutput 物件並將其設定作為擷取session的輸出裝置
            captureMetadataOutput = AVCaptureMetadataOutput()
            captureSession?.addOutput(captureMetadataOutput!)

            // 設定代理並使用預設的調度佇列來執行回呼（call back）
            captureMetadataOutput?.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            captureMetadataOutput?.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]
            
            // 初始化影像預覽層，並將其加為 viewPreview 視圖層的子層
            videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)
            videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
            videoPreviewLayer?.frame = view.layer.bounds
            //view.layer.addSublayer(videoPreviewLayer!)
            view.layer.insertSublayer(videoPreviewLayer!, below: view.layer.sublayers?[0])

            // 隱藏非必要視圖
            topMarginView.isHidden = true
            qrInterestView.isHidden = true
            
            // 開始影像擷取
            captureSession?.startRunning()
        } catch {
            //view.bringSubview(toFront: bottomStackView)
        // 假如有錯誤產生、 單純記錄其狀況，不再繼續。
            print("\(String(describing: error.localizedDescription))")
            
            // Declare Alert message
            let dialogMessage = UIAlertController(title: "请提供摄像头存取权限", message: "", preferredStyle: .alert)
            dialogMessage.view.tintColor = UIColor.black
            
            // Create OK button with action handler
            let ok = UIAlertAction(title: "知道了", style: .default, handler: { (action) -> Void in
            
            })
            
            //Add OK and Cancel button to dialog message
            dialogMessage.addAction(ok)
            
            // Present dialog message to user
            self.present(dialogMessage, animated: true, completion: nil)
            
        }
        
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        // 濾層
        let myRact = qrInterestView.frame
        let path = UIBezierPath(roundedRect: UIScreen.main.bounds, cornerRadius: 0)
        let rectanglePath = UIBezierPath(roundedRect: myRact, cornerRadius: 5)
        path.append(rectanglePath)
        path.usesEvenOddFillRule = true
        
        let fillLayer:CAShapeLayer = CAShapeLayer();
        fillLayer.path = path.cgPath;
        fillLayer.fillRule = CAShapeLayerFillRule.evenOdd;
        fillLayer.fillColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 1).cgColor
        fillLayer.opacity = 0.7;
        view.layer.insertSublayer(fillLayer, above: view.layer.sublayers?[0])

        // 觸發區域
        let xProportion: CGFloat = qrInterestView.frame.origin.y/view.frame.height
        let yProportion: CGFloat = qrInterestView.frame.origin.x/view.frame.width
        let widthProportion: CGFloat = qrInterestView.frame.height/view.frame.height
        let heightProportion: CGFloat = 1 - yProportion*2
        
        let restOfInterest = CGRect(
            x: xProportion,
            y: yProportion,
            width: widthProportion,
            height: heightProportion
        )
        
        captureMetadataOutput?.rectOfInterest = restOfInterest
    }
    
    /**** View Actions ****/
    @IBAction func buttonBackClick(_ sender: UIButton) {
        self.navigationController?.popViewController(animated: true)
    }
    
    @IBAction func buttonLightClick(_ sender: UIButton) {
        let device =  AVCaptureDevice.default(for: AVMediaType.video)
       // defaultDevice(withMediaType: AVMediaTypeVideo)!
        if (device?.hasTorch ?? false) {
            do {
                try device?.lockForConfiguration()
                if (device?.torchMode == AVCaptureDevice.TorchMode.on) {
                    device?.torchMode = AVCaptureDevice.TorchMode.off
                } else {
                    do {
                        try device?.setTorchModeOn(level: 1.0)
                    } catch {
                        print(error)
                    }
                }
                device?.unlockForConfiguration()
            } catch {
                print(error)
            }
        }
    }
    
    @IBAction func buttonManualEnterClick(_ sender: UIButton) {
        self.stopCaptureSession()
        var userIdTextField: UITextField?
        
        // Declare Alert message
        let dialogMessage = UIAlertController(title: "联系网站客服索取编号并输入", message: "", preferredStyle: .alert)
        dialogMessage.view.tintColor = UIColor.black
        
        // Create OK button with action handler
        let ok = UIAlertAction(title: "好的", style: .default, handler: { (action) -> Void in
            if let userInput = userIdTextField!.text {
                self.processMerchantValue(with: userInput, manualInput: true)
            }
        })
        
        // Create Cancel button with action handlder
        let cancel = UIAlertAction(title: "取消", style: .cancel) { (action) -> Void in
            self._loadView?.removeFromSuperview()
            self.captureSession?.startRunning()
            self.qrValue = nil
        }
        
        //Add OK and Cancel button to dialog message
        dialogMessage.addAction(cancel)
        dialogMessage.addAction(ok)
        
        // Add Input TextField to dialog message
        dialogMessage.addTextField { (textField) -> Void in
            
            userIdTextField = textField
            userIdTextField?.placeholder = "商戶"
        }
        
        // Present dialog message to user
        self.present(dialogMessage, animated: true, completion: nil)
    }
    
    @IBAction func buttonAlbumClick(_ sender: UIButton) {
        if UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum){
        
            imagePicker.delegate = self
            imagePicker.sourceType = .savedPhotosAlbum;
            imagePicker.allowsEditing = false
            
            self.present(imagePicker, animated: true, completion: nil)
        }
    }
    
    /**** Others ****/
    func alertMessageRseumeCapture(about: String, withDescription: String){
        let dialogMessage = UIAlertController(title: about, message: withDescription, preferredStyle: .alert)
        dialogMessage.view.tintColor = UIColor.black
        
        // Create OK button with action handler
        let ok = UIAlertAction(title: "好的", style: .default, handler: { (action) -> Void in
            //self.loadingOverlayiew.layer.isHidden = true
            self._loadView?.removeFromSuperview()
            self.captureSession?.startRunning()
            self.qrValue = nil
        })
        
        //Add OK and Cancel button to dialog message
        dialogMessage.addAction(ok)
        
        // Present dialog message to user
        self.present(dialogMessage, animated: true, completion: nil)
    }
    
    func stopCaptureSession(){
        self.captureSession?.stopRunning()
        self._loadView = UIHelper.initLoadView(self, withMessage: "读取中...")
        self.view.addSubview(self._loadView!)
        //self.loadingOverlayiew.layer.isHidden = false
    }
    
    func processMerchantValue(with qrValue: String, manualInput: Bool = false){
        if let clientDomain = processQRValue(qrValue) {
            if manualInput == false {
                self.qrValue = clientDomain.host!
                
                self.checkSiteValid(clientDomain)
                return
            }
        }
        self.qrValue = qrValue
        
        RequestHelper.get(GlobalInfo.resDomain, atPath: "/website.json", withCompletion: { (data: Data) -> Void in
            let clientListArray = try JSONSerialization.jsonObject(with: data, options: []) as! [String: String]
            if let clientDomain = clientListArray[qrValue] {

                var clientURL = URL(string: clientDomain)!
                if clientURL.scheme == nil {
                    clientURL = URL(string: "http://\(clientDomain)")!
                }
                
                self.checkSiteValid(clientURL)
                
            }else{
                self.alertMessageRseumeCapture(about: "无法连接该编号指定之站点", withDescription: "编号验证错误")
                self.qrValue = nil
            }
        }, withError: { error in
            self.alertMessageRseumeCapture(about: "无法获取配置文件信息，请联系客服", withDescription: "")
            self.qrValue = nil
        })
    }
    
    func checkSiteValid(_ clientDomain: URL){
        print("QR Checking Client: \(clientDomain.absoluteString)")

        RequestHelper.get(clientDomain.absoluteString, atPath: "/clientsAPIs/getInfo", withCompletion: { data in
     
            do{
                let clientListArray = try JSONSerialization.jsonObject(with: data, options: []) as? [String: String]
                      
                if clientListArray?["siteid"] != nil {
                    
                    //Return domain OK
                    DispatchQueue.main.async(execute: {
                      
                        self.delegate?.merchantResponse(clientDomain, clientListArray!)
                        self.navigationController?.popViewController(animated: true)
                    })
                    
                }else{
                    self.alertMessageRseumeCapture(about: "无法连接该编号指定之站点", withDescription: "编号验证错误")
                    self.qrValue = nil
                }
            }catch{
                self.alertMessageRseumeCapture(about: "无法连接该编号指定之站点", withDescription: "编号验证错误")
                self.qrValue = nil
            }
            
            
        }, withError: { error in
            self.alertMessageRseumeCapture(about: "无法连接该编号指定之站点", withDescription: "编号验证错误")
            self.qrValue = nil
        })
    }
    
    func processQRValue(_ qrValue: String) -> URL? {
        var url = URL(string: qrValue)
        
        if url != nil && url?.scheme == nil {
           url = URL(string: "http://\(qrValue)")
        }
        
        if let urlObj = url {
            if let clientsite = urlObj.queryItemsDictionary["clientsite"] {
                if let clientURL = URL(string: clientsite) {
                    if clientURL.scheme == nil {
                        return URL(string: "http://\(clientsite)")!
                    }
                    return clientURL
                }
            }
            
            if urlObj.host != nil{
                return urlObj
            }
        }
        return nil
    }
    
    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
        // 檢查 metadataObjects 陣列是否為非空值，它至少需包含一個物件
        if metadataObjects == nil || metadataObjects.count == 0 {
            return
        }
        
        // 取得元資料（metadata）物件
        let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
        if metadataObj.type == AVMetadataObject.ObjectType.qr {
            if metadataObj.stringValue != nil {
                if(qrValue == nil){
                    qrValue = metadataObj.stringValue
        
                    self.stopCaptureSession()
                    self.processMerchantValue(with: qrValue!)
                }
            }
        }
    }
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        self.stopCaptureSession()
        
        if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            self.dismiss(animated: true, completion: {() -> Void in
                let ciImage = CIImage(image: image)!
                
                let context = CIContext(options: nil)
                let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: context,
                                          options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
                
                let features = detector?.features(in: ciImage)
                
                if(features?.count == 0){
                    self.alertMessageRseumeCapture(about: "提示", withDescription: "该图片没有包含二维码！")
                }else if((features?.count)! > 1){
                    self.alertMessageRseumeCapture(about: "提示", withDescription: "该图片包含多於一个二维码！")
                }else{
                    let qrMessage = (features![0] as! CIQRCodeFeature).messageString
                    self.processMerchantValue(with: qrMessage!)
                }

            })
        } else{
            print("Something went wrong")
        }
        
        self.dismiss(animated: true, completion: {() -> Void in
            
        })
    }
}
